package com.dl698.axdr;

import com.dl698.asn1.axdr.AxdrType;
import com.dl698.util.ReverseByteArrayInputStream;
import com.dl698.util.ReverseByteArrayOutputStream;

import java.util.ArrayList;
import java.util.List;

/**
 * AxdrStructure类
 * 实现结构体数据的编解码
 * 
 * @author wind
 * @version 1.1.1
 */
public class AxdrStructure implements AxdrType {
    private List<Data> elements = new ArrayList<>();
    private int length = 0;

    public AxdrStructure() {
    }

    public void setLength(int length) {
        this.length = length;
    }

    public List<Data> getElements() {
        return elements;
    }

    @Override
    public int decode(ReverseByteArrayInputStream input) {
        int codeLength = 0;

        // 解码结构体长度
        Unsigned8 lengthField = new Unsigned8();
        lengthField.setConst();
        codeLength += lengthField.decode(input);
        this.length = (int) lengthField.getValue();

        // 解码结构体元素
        for (int i = 0; i < this.length; i++) {
            Data element = new Data();
            codeLength += element.decode(input);
            this.elements.add(element);
        }

        return codeLength;
    }

    @Override
    public int encode(ReverseByteArrayOutputStream output) {
        int codeLength = 0;

        // 编码结构体长度
        Unsigned8 lengthField = new Unsigned8();
        lengthField.setConst();
        lengthField.setMinMaxVal(0, 255, this.length);
        codeLength += lengthField.encode(output);

        // 编码结构体元素
        for (Data element : this.elements) {
            codeLength += element.encode(output);
        }

        return codeLength;
    }

    /**
     * 编码并保存
     * 
     * @param encodingSizeGuess 编码大小预估
     */
    public void encodeAndSave(int encodingSizeGuess) {
        ReverseByteArrayOutputStream revOStream = new ReverseByteArrayOutputStream();
        revOStream.setBufSize(encodingSizeGuess);
        this.encode(revOStream);
        // 注意：这里没有dataCode字段，所以不保存到dataCode
    }

    /**
     * 获取结构体大小
     * 
     * @return 结构体大小
     */
    public int size() {
        return this.elements.size();
    }

    /**
     * 根据索引获取元素
     * 
     * @param index 索引
     * @return 数据元素
     */
    public Data get(int index) {
        if (index >= 0 && index < this.elements.size()) {
            return this.elements.get(index);
        }
        return null;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("structure[").append(this.length).append("]: {");
        for (int i = 0; i < this.elements.size(); i++) {
            if (i > 0) {
                sb.append(", ");
            }
            sb.append(this.elements.get(i).toString());
        }
        sb.append("}");
        return sb.toString();
    }
}